home *** CD-ROM | disk | FTP | other *** search
/ GFX Sensations 1 / Graphic Sensations - Volume 1.iso / tools / amiga / 3d_tools / irit40s.lha / Irit / geom_lib / intrnrml.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-30  |  5.6 KB  |  180 lines

  1. /*****************************************************************************
  2. *   "Irit" - the 3d (not only polygonal) solid modeller.             *
  3. *                                         *
  4. * Written by:  Gershon Elber                Ver 0.2, Aug. 1990   *
  5. ******************************************************************************
  6. *   Module to interplate internal vertices using vertices on the given       *
  7. * convex boundary OriginalVList. All internal vertices are assumed to be in  *
  8. * the interior of the convex region defined by OriginalVList or on its       *
  9. * boundary.                                     *
  10. *****************************************************************************/
  11.  
  12. #include <math.h>
  13. #include "irit_sm.h"
  14. #include "iritprsr.h"
  15. #include "geomat3d.h"
  16. #include "intrnrml.h"
  17.  
  18. /* #define DEBUG1          To define polygon (with normals printing routine. */
  19.  
  20. static void UpdateOneVertexNormal(IPVertexStruct *VUpdate,
  21.                   IPPolygonStruct *OriginalPl);
  22.  
  23. #ifdef DEBUG1 
  24. static void PrintPolygon(IPPolygonStruct *Pl);
  25. #endif /* DEBUG1 */
  26.  
  27. /*****************************************************************************
  28. *   For each polygon in PlList update any vertex normal which is zero to an  *
  29. *interpolated value using the Original polygon vertex list OriginalVList.    *
  30. *   All the new vertices are enclosed within the original polygon which      *
  31. * must be convex as well.                             *
  32. *****************************************************************************/
  33. void UpdateVerticesNormals(IPPolygonStruct *PlList, IPPolygonStruct *OriginalPl)
  34. {
  35.     IPVertexStruct *V, *VHead;
  36.  
  37.     while (PlList) {
  38.     V = VHead = PlList -> PVertex;
  39.     do {
  40.         if (APX_EQ(V -> Normal[0], 0.0) &&
  41.         APX_EQ(V -> Normal[1], 0.0) &&
  42.         APX_EQ(V -> Normal[2], 0.0)) {
  43.         /* This vertex need to be updated. */
  44.         UpdateOneVertexNormal(V, OriginalPl);
  45.         }
  46.  
  47.         V = V -> Pnext;
  48.     }
  49.     while (V != NULL && V != VHead);
  50.  
  51.     PlList = PlList -> Pnext;
  52.     }
  53. }
  54.  
  55. /*****************************************************************************
  56. *   Update one vertex normal be a convex blend of boundary vertices normals  *
  57. *****************************************************************************/
  58. static void UpdateOneVertexNormal(IPVertexStruct *VUpdate,
  59.                   IPPolygonStruct *OriginalPl)
  60. {
  61.     IPVertexStruct *V,
  62.     *OriginalVList = OriginalPl -> PVertex;
  63.  
  64.     V = OriginalVList;
  65.     do {
  66.     if (Colinear3Vertices(V, VUpdate, V -> Pnext)) {
  67.         /* Interpolate the normal according to the edge vertices VUpdate */
  68.         /* is on and according to the distance of VUpdate to edge ends.  */
  69.         InterpNrmlBetweenTwo(VUpdate, V, V -> Pnext);
  70.         return;
  71.     }
  72.     V = V -> Pnext;
  73.     }
  74.     while (V != NULL && V != OriginalVList);
  75.  
  76.     /* If we are here then the point is not on the polygon boundary and in   */
  77.     /* that case we simply use the polygon normal as an approximation.       */
  78.     PT_COPY(VUpdate -> Normal, OriginalPl -> Plane);
  79. }
  80.  
  81. /*****************************************************************************
  82. *   Returns TRUE iff the 3 vertices are colinear.                 *
  83. *****************************************************************************/
  84. int Colinear3Vertices(IPVertexStruct *V1, IPVertexStruct *V2,
  85.                             IPVertexStruct *V3)
  86. {
  87.     RealType l;
  88.     VectorType V12, V23, V;
  89.  
  90.     if (PT_APX_EQ(V1 -> Coord, V2 -> Coord) ||
  91.     PT_APX_EQ(V2 -> Coord, V3 -> Coord))
  92.     return TRUE;
  93.  
  94.     PT_SUB(V12, V1 -> Coord, V2 -> Coord);
  95.     PT_SUB(V23, V2 -> Coord, V3 -> Coord);
  96.  
  97.     /* Make sure the middle point is in fact in the middle. */
  98.     if (V12[0] * V23[0] < -EPSILON ||
  99.         V12[1] * V23[1] < -EPSILON ||
  100.     V12[2] * V23[2] < -EPSILON)
  101.     return FALSE;
  102.  
  103.     GMVecCrossProd(V, V12, V23);
  104.  
  105.     l = PT_LENGTH(V);
  106.  
  107.     return APX_EQ(l, 0.0);
  108. }
  109.  
  110. /*****************************************************************************
  111. *   Update Normal of the middle vertex V, assumed to be between V1 and V2.   *
  112. *****************************************************************************/
  113. void InterpNrmlBetweenTwo(IPVertexStruct *V, IPVertexStruct *V1,
  114.                             IPVertexStruct *V2)
  115. {
  116.     RealType t1, t2;
  117.     VectorType Vec1, Vec2;
  118.  
  119.     PT_SUB(Vec1, V -> Coord, V1 -> Coord);
  120.     PT_SUB(Vec2, V -> Coord, V2 -> Coord);
  121.     t1 = PT_LENGTH(Vec1);
  122.     t2 = PT_LENGTH(Vec2);
  123.  
  124.     PT_COPY(Vec1, V1 -> Normal);
  125.     PT_COPY(Vec2, V2 -> Normal);
  126.     PT_SCALE(Vec1, t2);
  127.     PT_SCALE(Vec2, t1);
  128.     PT_ADD(V -> Normal, Vec1, Vec2);
  129.  
  130.     PT_NORMALIZE(V -> Normal);
  131. }
  132.  
  133. /*****************************************************************************
  134. *   Copute Normal from middle position of Pt Between V1 and V2.             *
  135. *****************************************************************************/
  136. void InterpNrmlBetweenTwo2(PointType Pt, VectorType Normal,
  137.                IPVertexStruct *V1, IPVertexStruct *V2)
  138. {
  139.     RealType t1, t2;
  140.     VectorType Vec1, Vec2;
  141.  
  142.     PT_SUB(Vec1, Pt, V1 -> Coord);
  143.     PT_SUB(Vec2, Pt, V2 -> Coord);
  144.     t1 = PT_LENGTH(Vec1);
  145.     t2 = PT_LENGTH(Vec2);
  146.  
  147.     PT_COPY(Vec1, V1 -> Normal);
  148.     PT_COPY(Vec2, V2 -> Normal);
  149.     PT_SCALE(Vec1, t2);
  150.     PT_SCALE(Vec2, t1);
  151.     PT_ADD(Normal, Vec1, Vec2);
  152.  
  153.     PT_NORMALIZE(Normal);
  154. }
  155.  
  156. #ifdef DEBUG1 
  157.  
  158. /*****************************************************************************
  159. *   Print the content of the given polygon, to standard output.             *
  160. *****************************************************************************/
  161. static void PrintPolygon(IPPolygonStruct *Pl)
  162. {
  163.     IPVertexStruct *V = Pl -> Coord,
  164.          *VHead = V;
  165.  
  166.     do {
  167.     printf("    %10lg %10lg %10lg (%10lg %10lg %10lg)",
  168.            V -> Coord[0], V -> Coord[1], V -> Coord[2],
  169.            V -> Normal[0], V -> Normal[1], V -> Normal[2]);
  170.     if (IS_INTERNAL_EDGE(V))
  171.         printf(" (Internal)\n");
  172.     else
  173.         printf("\n");
  174.     V = V -> Pnext;
  175.     }
  176.     while (V!= NULL && V != VHead);
  177. }
  178.  
  179. #endif /* DEBUG1 */
  180.